<template>
    <div>
        <el-collapse v-for="path in pathsByTag" :key="path.method + path.location" style="margin-top:15px; margin-bottom:15px;">
            <el-collapse-item :name="path.method + path.location">
                <template slot="title">
                    <div class="path-title-div">
                        <el-tag v-if="path.method === 'get'" class="path-title-method">GET</el-tag>
                        <el-tag type="success" v-if="path.method === 'post'" class="path-title-method">POST</el-tag>
                        <el-tag type="warning" v-if="path.method === 'put'" class="path-title-method">PUT</el-tag>
                        <el-tag type="danger" v-if="path.method === 'delete'" class="path-title-method">DELETE</el-tag>
                        <el-tag type="info" color v-if="path.method === 'head'" class="path-title-method">HEAD</el-tag>
                        <el-tag type="info" v-if="path.method === 'options'" class="path-title-method">OPTIONS</el-tag>
                        <el-tag type="info" v-if="path.method === 'patch'" class="path-title-method">PATCH</el-tag>
                        <span class="path-title-location">{{path.location}}</span>
                        <span class="path-title-summary">{{path.summary === undefined ? '' : path.summary}}</span>
                    </div>
                </template>
                <div class="path-content-div">
                    <Notes :path="path"></Notes>
                    <Parameters :path="path"></Parameters>
                    <Responses :path="path"></Responses>
                    <Test :path="path"></Test>
                </div>
            </el-collapse-item>
        </el-collapse>
    </div>
</template>

<script>
  import { mapGetters } from 'vuex';
  import Notes from './notes';
  import Parameters from './parameters';
  import Responses from './responses';
  import Test from './test';
  export default {
    name: "paths",
    components: {
      Notes,
      Parameters,
      Responses,
      Test
    },
    computed: {
      ...mapGetters([
        'pathsByTag',
        'definitions'
      ])
    },
    provide() {
      return {
        rowKey: this.rowKey,
        expandClass: this.expandClass,
        formatRequired: this.formatRequired,
        formatDataType: this.formatDataType,
        getDataType: this.getDataType,
        getBodyDataType: this.getBodyDataType,
        getModel: this.getModel,
        getArrayModel: this.getArrayModel,
        getDefModel: this.getDefModel,
        getExample: this.getExample,
        getArrayExample: this.getArrayExample,
        getDefExample: this.getDefExample,
        getSpaces: this.getSpaces,
        getValue: this.getValue
      }
    },
    methods: {
      rowKey(row) {
        return row.name;
      },
      expandClass(row) {
        if (row.row.schema !== undefined && (row.row.schema.$ref !== undefined || row.row.schema.type === 'array' || row.row.schema.type == 'object')) {
          return '';
        } else {
          return 'hide-row';
        }
      },
      formatRequired(row) {
        return row.required ? 'true' : 'false';
      },
      formatDataType(row) {
        if (row.type !== undefined) {
          return this.getDataType(row);
        } else if (row.schema !== undefined) {
          return this.getBodyDataType(row.schema);
        } else if (row.items !== undefined && row.items.type === 'object') {
          return 'object';
        }
      },
      getDataType(data) {
        if (data.type === 'integer' && data.format === 'int32') {
          return 'integer';
        }
        if (data.type === 'integer' && data.format === 'int64') {
          return 'long';
        }
        if (data.type === 'number' && data.format === 'double') {
          return 'double';
        }
        if (data.type === 'number' && data.format === 'float') {
          return 'float';
        }
        if (data.type === 'boolean') {
          return 'boolean';
        }
        if (data.type === 'string' && !data.format) {
          return 'string';
        }
        if (data.type === 'string' && data.format === 'date-time') {
          return 'dateTime';
        }
        if (data.type === 'string' && data.format === 'byte') {
          return 'byte';
        }
        if (data.type === 'file') {
          return 'file';
        }
        if (data.type === 'array') {
          if (data.items.type !== undefined) {
            return 'array[' + this.getDataType(data.items) + ']';
          } else if (data.items.$ref !== undefined) {
            return 'array[' + data.items.$ref.replace('#/definitions/', '') + ']';
          }
        }
        return data.type;
      },
      getBodyDataType(schema) {
        if (schema.type !== undefined) {
          return this.getDataType(schema);
        } else if (schema.$ref !== undefined) {
          return schema.$ref.replace('#/definitions/', '');
        }
      },
      getModel(schema) {
        const defArr = [];
        if (schema.type !== undefined) {
          if (schema.type === 'array') {
            return this.getArrayModel(schema, 1, defArr);
          } else if (schema.type === 'object') {
            return 'Object {}';
          }
        } else if (schema.$ref !== undefined) {
          const modelName = schema.$ref.replace('#/definitions/', '');
          return this.getDefModel(modelName, 1, defArr);
        }
      },
      getArrayModel(schema, deep, defArr) {
        if (schema.items.$ref !== undefined) {
          const modelName = schema.items.$ref.replace("#/definitions/", '');
          if (defArr.indexOf(modelName) >= 0) {
            return 'Array [' + modelName + '{}]';
          } else {
            return 'Array [\n' + this.getSpaces(deep) + this.getDefModel(schema.items.$ref.replace('#/definitions/', ''), deep + 1, defArr) + '\n' + this.getSpaces(deep - 1) + ']';
          }
        } else if(schema.items.type !== undefined && schema.items.type === 'array') {
          return 'Array [\n' + this.getSpaces(deep) + this.getArrayModel(schema.items, deep + 1, defArr) + '\n' + this.getSpaces(deep - 1) + ']';
        } else if (schema.items.type !== undefined && schema.items.type == 'object') {
          return 'Array [{}]';
        } else {
          return 'Array [' + this.getDataType(schema.items) + ']';
        }
      },
      getDefModel(modelName, deep, defArr) {
        defArr.push(modelName);
        const properties = this.definitions[modelName].properties;
        if (properties !== undefined) {
          let model = modelName + ' {';
          const keys = Object.keys(properties);
          for (let i = 0; i < keys.length; i ++) {
            const key = keys[i];
            const property = properties[key];
            if (property.type !== undefined && property.type !== null) {
              if (property.type == 'array') {
                model += '\n' + this.getSpaces(deep) + key + ': ' + this.getArrayModel(property, deep + 1, defArr);
              } else if (property.type == 'object') {
                model += '\n' + this.getSpaces(deep) + key + ': Object {}';
              } else {
                model += '\n' + this.getSpaces(deep) + key + ': ' + this.getDataType(property);
              }
            } else if (property.$ref !== undefined && property.$ref !== null) {
              const ref = property.$ref.replace('#/definitions/', '');
              if (defArr.indexOf(ref) >= 0) {
                model += '\n' + this.getSpaces(deep) + key + ': ' + ref + '{}';
              } else {
                model += '\n' + this.getSpaces(deep) + key + ': ' + this.getDefModel(ref, deep + 1, defArr);
              }
            }
            if ( i !== keys.length - 1) {
              model += ',';
            }
            model += property.description ? ' //' + property.description : '';
          }
          model += '\n' + this.getSpaces(deep - 1) + '}';
          return model;
        } else {
          return 'Object {}';
        }
      },
      getExample(schema, example) {
        if (example !== undefined) {
          return example.replace(/\t/g, '    ');
        } else if (schema !== undefined) {
          const defArr = [];
          if (schema.type !== undefined) {
            if (schema.type === 'array') {
              return this.getArrayExample(schema, 1, defArr);
            } else if (schema.type === 'object') {
              return '{}';
            }
          } else if (schema.$ref !== undefined) {
            const modelName = schema.$ref.replace('#/definitions/', '');
            return this.getDefExample(modelName, 1, defArr);
          }
        }
      },
      getArrayExample(schema, deep, defArr) {
        if (schema.items.$ref !== undefined) {
          const modelName = schema.items.$ref.replace("#/definitions/", '');
          if (defArr.indexOf(modelName) >= 0) {
            return '[{}]';
          } else {
            return '[\n' + this.getSpaces(deep) + this.getDefExample(schema.items.$ref.replace('#/definitions/', ''), deep + 1, defArr) + '\n' + this.getSpaces(deep - 1) + ']';
          }
        } else if(schema.items.type !== undefined && schema.items.type === 'array') {
          return '[\n' + this.getSpaces(deep) + this.getArrayExample(schema.items, deep + 1, defArr) + '\n' + this.getSpaces(deep - 1) + ']';
        } else if (schema.items.type !== undefined && schema.items.type == 'object') {
          return '[{}]';
        } else {
          return '[' + this.getValue(schema.items.example, this.getDataType(schema.items)) + ']';
        }
      },
      getDefExample(modelName, deep, defArr) {
        defArr.push(modelName);
        const properties = this.definitions[modelName].properties;
        if (properties !== undefined) {
          let model = '{';
          Object.keys(properties).forEach(key => {
            const property = properties[key];
            if (property.type !== undefined && property.type !== null) {
              if (property.type == 'array') {
                model += '\n' + this.getSpaces(deep) + '"' + key + '": ' + this.getArrayExample(property, deep + 1, defArr) + ',';
              } else if (property.type == 'object') {
                model += '\n' + this.getSpaces(deep) + '"' + key + '": Object{},';
              } else {
                model += '\n' + this.getSpaces(deep) + '"' + key + '": ' + this.getValue(property.example, this.getDataType(property)) + ',';
              }
            } else if (property.$ref !== undefined && property.$ref !== null) {
              const ref = property.$ref.replace('#/definitions/', '');
              if (defArr.indexOf(ref) >= 0) {
                model += '\n' + this.getSpaces(deep) + '"' + key + '": ' + '{},';
              } else {
                model += '\n' + this.getSpaces(deep) + '"' + key + '": ' + this.getDefExample(ref, deep + 1, defArr) + ',';
              }
            }
          });
          if (Object.keys(properties).length > 0) {
            model = model.substr(0, model.length - 1);
          }
          model += '\n' + this.getSpaces(deep - 1) + '}';
          return model;
        } else {
          return '{}';
        }
      },
      getSpaces(deep) {
        let spaces = '';
        for(let i = 0; i < deep * 4; i ++) {
          spaces += ' ';
        }
        return spaces;
      },
      getValue(example, type) {
        if (example !== undefined) {
          if (type === 'string' || type == 'dateTime') {
            return '"' + example + '"'
          }
          return example;
        } else {
          if (type === 'string') {
            return '"string"';
          } else if (type === 'integer' || type === 'byte' || type === 'short' || type === 'long' || type === 'float' || type === 'double') {
            return '0';
          } else if (type === 'boolean') {
            return 'true';
          } else if (type === 'file') {
            return 'file';
          } else if (type === 'dateTime') {
            const time = new Date();
            const year = time.getFullYear();
            const month = time.getMonth() + 1 >= 10 ? (time.getMonth() + 1) : '0' + (time.getMonth() + 1);
            const date = time.getDate() >= 10 ? time.getDate() : '0' + time.getDate();
            const hours = time.getHours() >= 10 ? time.getHours() : '0' + time.getHours();
            const minutes = time.getMinutes() >= 10 ? time.getMinutes() : '0' + time.getMinutes();
            const seconds = time.getSeconds() >= 10 ? time.getSeconds() : '0' + time.getSeconds();
            return '"' + year + '-' + month + '-' + date + ' ' + hours + ':' + minutes + ':' + seconds + '"';
          }
        }
      }
    }
  }
</script>

<style scoped>
    .path-title-div {
        width: 100%;
        padding: 0 15px;
        white-space: nowrap;
        word-break: break-all;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .path-title-method {
        display: inline-block;
        text-align: center;
        width: 80px;
    }

    .path-title-location {
        display: inline-block;
        margin-left: 15px;
    }

    .path-title-summary {
        color: #64758E;
        margin-left: 15px;
    }

    .path-content-div {
        width: 100%;
        padding: 15px 15px;
        box-sizing: border-box;
    }
</style>